<script setup lang="ts">
import { onBeforeUnmount, ref, shallowRef } from 'vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { getStore } from '@/utils/store'
import { DowloadPreviewImage } from '@/utils/util'

type InsertFnType = (url: string, alt?: string, href?: string, poster?: string) => void

type Props = {
	height?: string
	modelValue?: string
	EventChange?: Function
	formRef?: any
}
const props = withDefaults(defineProps<Props>(), {
	height: '500px',
})
const emit = defineEmits(['update:modelValue'])

// 编辑器实例，必须用 shallowRef，重要！
const editorRef = shallowRef()
const valueHtml = ref(props.modelValue)

// 内容 HTML
const blobToDataURI = (blob) => {
	return new Promise((resolve, reject) => {
		const reader = new FileReader()
		reader.readAsDataURL(blob)
		reader.onload = function (e) {
			resolve(e.target.result)
		}
	})
}

const userInfo = getStore('userInfo') || {}
const mod = import.meta.env.MODE
const hostname = mod == 'development' ? '/api' : window.location.origin
const getPreviewImage = async (src) => {
	let srcStr = src
	if (src && src.includes('ningxiang')) {
		const nSrc = (await DowloadPreviewImage(src, 'blob')) as string
		srcStr = await blobToDataURI(nSrc)
	}
	return Promise.resolve(srcStr)
}

// 编辑器配置
const editorConfig = {
	placeholder: '请输入内容...',
	MENU_CONF: {
		uploadImage: {
			fieldName: 'uploadFile',
			meta: {},
			server: `${hostname}/admin/obs/uploadFile`,
			headers: {
				Authorization: 'Bearer ' + userInfo.access_token,
			},
			customInsert: async (res: any, insertFn: InsertFnType) => {
				const src = await getPreviewImage(res.data)
				insertFn(src, '', '')
			},
		},
		uploadVideo: {
			fieldName: 'uploadFile',
			meta: {},
			server: `${hostname}/admin/obs/uploadFile`,
			headers: {
				Authorization: 'Bearer ' + userInfo.access_token,
			},
			customInsert: async (res: any, insertFn: InsertFnType) => {
				const src = await getPreviewImage(res.data)
				insertFn(src, '', '')
			},
		},
	},
}
// 工具栏配置
const toolbarConfig = {
	excludeKeys: [],
	modalAppendToBody: true,
}
const handleCreated = (editor) => {
	editorRef.value = editor // 记录 editor 实例，重要！
	editor.setHtml(props.modelValue)
}
const onUpdate = (e) => {
	props.EventChange && props.EventChange('update', e)
	// 如果没有输入内容，那么就会将内容设为空
	if (e === '<p><br></p>') {
		emit('update:modelValue', '')
		return
	}
	emit('update:modelValue', e)
}
// 当失焦时进行表单校验
const onBlur = (e) => {
	props.formRef?.formRef?.validateField(props.formRef.prop)
}

// 组件销毁时，及时销毁编辑器
onBeforeUnmount(() => {
	const editor = editorRef.value
	if (editor == null) return
	editor.destroy()
})
</script>

<template>
	<div style="border: 1px solid #ccc">
		<!-- 工具栏 -->
		<Toolbar :editor="editorRef" :defaultConfig="toolbarConfig" style="border-bottom: 1px solid #ccc" />
		<!-- 编辑器 -->
		<Editor
			v-model="valueHtml"
			:defaultConfig="editorConfig"
			:style="{ height: height, overflowY: 'hidden' }"
			@onCreated="handleCreated"
			@update:modelValue="onUpdate"
			@onBlur="onBlur"
		/>
	</div>
</template>

<style src="@wangeditor/editor/dist/css/style.css"></style>
